#define MSSTRING_C
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <malloc.h>
#include <libmslog/mslog.h>
#include "msstring.h"
#include "mscommon.h"
#define FLAG "STRING"

size_t msstr_api_lcpy(ms_string ms_in dst, ms_cstring ms_in src, size_t ms_in size)
{
	size_t len = 0;
	while (++len < size && *src){
        *dst++ = *src++;
	}
    if (len <= size){
       	*dst = 0;
    }
    return len + strlen(src) - 1;
}

size_t msstr_api_lcat(ms_string ms_in dst, ms_string ms_in src, size_t ms_in size)
{
    size_t len = strlen(dst);
    if (size <= len + 1){
		return len + strlen(src);
	}
    return len + msstr_api_lcpy(dst + len, src, size - len);
}

size_t msstr_api_lcatf(ms_string ms_in dst, size_t ms_in size, ms_cstring ms_in fmt, ...)
{
	int len = strlen(dst);
    va_list vl;

    va_start(vl, fmt);
    len += vsnprintf(dst + len, size > len ? size - len : 0, fmt, vl);
    va_end(vl);

    return len;
}

ms_bool msstr_api_isSpace(ms_s08 ms_in c)
{
	return (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' ||c == '\v')  ?  ms_true : ms_false;
}
//以'\n'为行结束符
ms_void msstr_api_getLine(ms_ps08 ms_in buf, ms_s32 ms_in buf_size, ms_pcstring ms_io pp)
{
	char *q = (char *)buf;
	const char *p = *pp;

	//size_t strspn (const char *s,const char * accept);
	//函数说明 strspn()从参数s字符串的开头计算连续的字符，而这些字符都完全是accept 所指字符串中的字符。简单的说，若strspn()返回的数值为n，则代表字符串s 开头连续有n 个字符都是属于字符串accept内的字符。
	p += strspn(p,  "\n");
	while (( '\n'!=(*p)) && ('\0'!=(*p))) {
		if ((q - (char *)buf) < buf_size - 1){
			*q++ = *p;
		}
		p++;
	}
    if (buf_size > 0){
    	*q = '\0';
    }
	*pp = p;
}
//以'\r'或'\n'为行结束符
ms_void msstr_api_getLine2(ms_ps08 ms_in buf, ms_s32 ms_in buf_size, ms_pcstring ms_io pp)
{
	char *q = (char *)buf;
	const char *p = *pp;
	p += strspn(p,  "\n");
	while (( '\r'!=(*p)) && ( '\n'!=(*p)) && ('\0'!=(*p))) {
		if ((q - (char *)buf) < buf_size - 1){
			*q++ = *p;
		}
		p++;
	}
    if (buf_size > 0){
        *q = '\0';
    }
	*pp = p;
}
//以\n'为行结束符,返回行中带结束符
ms_void msstr_api_getLine3(ms_ps08 ms_in buf, ms_s32 ms_in buf_size, ms_pcstring ms_io pp)
{
	char *q = (char *)buf;
	const char *p = *pp;

	p += strspn(p,  "\n");
	while (( '\n'!=(*p)) && ('\0'!=(*p))) {
		if ((q - (char *)buf) < buf_size - 2){
			*q++ = *p;
		}
		p++;
	}
	//获取'\n'字符
	*q++ = *p;p++;
	
    if (buf_size > 0){
       	*q = '\0';
    }
	*pp = p;
}

ms_void msstr_api_getWord(ms_ps08 ms_in buf, ms_s32 ms_in buf_size, ms_pcstring ms_io pp)
{
	#define SPACE_CHARS " \t\r\n"
	char *q = (char *)buf;
	const char *p = *pp;
	
	p += strspn(p, SPACE_CHARS);
	while (!msstr_api_isSpace(*p) && *p != '\0') {
		if ((q - (char *)buf) < buf_size - 1){
			*q++ = *p;
		}
		p++;
	}
    if (buf_size > 0){
		*q = '\0';
    }
	*pp = p;
}
/*strSrc是否在strItem中存在？忽略大小写*/
ms_bool msstr_api_isCasestr_IgnoreLetterCase(ms_cstring ms_in strSrc, ms_cstring ms_in strItem)
{
	return (0!=mslog_api_strCasestrNum(strSrc, strItem,ms_true,ms_false))? ms_true : ms_false;
}
/*strSrc是否在strItem中存在？*/
ms_bool msstr_api_isCasestr(ms_cstring ms_in strSrc, ms_cstring ms_in strItem)
{
	return (0!=mslog_api_strCasestrNum(strSrc, strItem,ms_true,ms_true))? ms_true : ms_false;
}
/*以strDelimit将strSrc分割成n段，并通过strOut进行输出。借助函数strtok实现，某些情况会导致段错误*/
ms_u32 msstr_api_split(ms_string ms_in strSrc,ms_cstring ms_in strDelimit,ms_string ms_out strOut[])
{
	if(ms_null==strSrc
		||ms_null==strDelimit){
		return 0;
	}
	if(0==strlen(strSrc)){
		return 0;
	}
	ms_u32 strnum=0;
	char *saveptr=ms_null;
	ms_ps08 p= strtok_r(strSrc,(ms_cstring)strDelimit,&saveptr);
	
	if(p) {strOut[strnum]=p;}
	while(p){
		p=strtok_r(NULL,(ms_cstring)strDelimit,&saveptr);
		if(p){
			strnum++;
			strOut[strnum]=p;
		}
	}
	strnum+= 1;
	return strnum;
}
/*以strDelimit将strSrc分割成n段，并通过strOut进行输出。自己代码实现*/
ms_u32 msstr_api_split2(ms_string ms_in strSrc,ms_cstring ms_in strDelimit,ms_string ms_out strOut[])
{
	if((0==strlen(strSrc))
		||(0==strlen(strDelimit))
		||(strlen(strSrc)<strlen(strDelimit))){
		return 0;
	}
	
	ms_u32 strnum=0;
	ms_s32 len_delimit=strlen(strDelimit);
	ms_s32 len_try=(strlen(strSrc)+1-strlen(strDelimit));
	ms_string pstr=strSrc;
	ms_s32 index=0;
	ms_string pstr_mark=pstr;
	strOut[strnum]=pstr_mark;
	strnum+= 1;
	for(index=0;index<len_try;){
		//ms_debug("----%s--%s",&pstr[index], strDelimit);
		if(ms_strncmp_seq(&pstr[index], strDelimit)){
			//ms_debug("Ok,it is you----%s--%s",&pstr[index], strDelimit);
			pstr[index]=0;
			index+=len_delimit;
			if(index<len_try){
				strOut[strnum]=pstr_mark=&pstr[index];
				strnum+= 1;
			}else{
				break;
			}
		}else{
			index++;
		}
	}
//	for(index=0;index<strnum;index++){
//		ms_debug("%03d----%s",index+1,strOut[index]);
//	}	
	return strnum;
}
/*URL地址分拆，获取协议、授权信息、主机名、端口和PATH等信息*/
ms_void msstr_api_urlSplit(ms_string ms_out proto, ms_s32 ms_in proto_size,
                  ms_string ms_out authorization, ms_s32 ms_in authorization_size,
                  ms_string ms_out hostname, ms_s32 ms_in hostname_size,
                  ms_ps32 port_ptr,
                  ms_string ms_out path, ms_s32 ms_in path_size,
                  ms_bool *pflag_ipv6,
                  ms_cstring ms_in url)
{
	const char *p, *ls, *at, *col, *brk;
	if (port_ptr){
		*port_ptr = -1;
	}
	if (proto_size > 0){
		proto[0] = 0;
	}
	if (authorization_size > 0){
		authorization[0] = 0;
	}
	if (hostname_size > 0){
		hostname[0] = 0;
	}
	if (path_size > 0) {
		path[0] = 0;
	}
	/* parse protocol */
	if ((p = strchr(url, ':'))) {
		msstr_api_lcpy(proto, url, ms_min(proto_size, p + 1 - url));
		p++; /* skip ':' */
		if (*p == '/') {
			p++;
		}
		if (*p == '/') {
			p++;
		}
	} else {
		/* no protocol means plain filename */
		msstr_api_lcpy(path, url, path_size);
		return;
	}

	/* separate path from hostname */
	ls = strchr(p, '/');
	if(!ls){
		ls = strchr(p, '?');
	}
	if(ls){
		msstr_api_lcpy(path, (ms_string)ls, path_size);
	}else{
		ls = &p[strlen(p)]; // XXX
	}
	/* the rest is hostname, use that to parse auth/port */
	if (ls != p) {
		/* authorization (user[:pass]@hostname) */
		if ((at = strchr(p, '@')) && at < ls) {
			msstr_api_lcpy(authorization, p,ms_min(authorization_size, at + 1 - p));
			p = at + 1; /* skip '@' */
		}
		if (*p == '[' && (brk = strchr(p, ']')) && brk < ls) {
			/* [host]:port */
			msstr_api_lcpy(hostname, p + 1,ms_min(hostname_size, brk - p));
			if (brk[1] == ':' && port_ptr){
				*port_ptr = atoi(brk + 2);
			}
			(*pflag_ipv6)=ms_true;
		} else if ((col = strchr(p, ':')) && col < ls) {
			(*pflag_ipv6)=ms_false;
			msstr_api_lcpy(hostname, (ms_string)p,ms_min(col + 1 - p, hostname_size));
			if (port_ptr){
				*port_ptr = atoi(col + 1);
			}
		} else{
			(*pflag_ipv6)=ms_false;
			msstr_api_lcpy(hostname, p,ms_min(ls + 1 - p, hostname_size));
		}
	}
}
/*构建listnum个URL地址，并将结果存放到plisturl中*/
ms_void  msstr_api_buildListurl(ms_string ms_in proto,ms_string ms_in authorization,
	ms_string ms_in hostname,ms_s32 ms_in port,ms_string ms_in path,ms_s32 ms_in listnum,ms_s32 ms_in arrsize,ms_byte * ms_out plisturl)
{
	char tbuf[1024]={0};
	//udp,rtp,rtmp,rtsp,hls,file
	ms_s32 index=0;
	for(index=0;index<listnum;index++){
		ms_string purl=&plisturl[index*arrsize];
		if(ms_buflen(proto)>0){
			ms_strcats(tbuf, purl, "%s://", proto);
		}	
		if(ms_buflen(authorization)>0){
			ms_strcats(tbuf, purl, "@%s@", authorization);
		}
		if(ms_buflen(hostname)>0){
			ms_strcats(tbuf, purl, "%s", hostname);
		}
		if(ms_buflen(path)>0){
			if(port>0){
				ms_strcats(tbuf, purl, ":%d", port);
			}
			if(msstr_api_isCasestr(path, "m3u8")){
				ms_strcats(tbuf, purl, "%s",path);
				ms_u32 offset_path=ms_buflen(path)-ms_buflen(".m3u8");
				ms_sprintf(&purl[offset_path], "_%03d.m3u8",index);
			}else{
				ms_strcats(tbuf, purl, "/%s_%03d", path,index);
			}
		}else{
			ms_strcats(tbuf, purl, ":%d", (port+index));
		}
		ms_debug("%03d.%s",index,purl);
	}
}
/*构建listnum个URL的字符串，用于信息显示*/
ms_void  msstr_api_buildListurl2(ms_string ms_in proto,ms_string ms_in authorization,
	ms_string ms_in hostname,ms_s32 ms_in port,ms_string ms_in path,ms_s32 ms_in listnum,ms_byte * ms_out plisturl)
{
	char tbuf[1024]={0};
	//udp,rtp,rtmp,rtsp,hls,file
	ms_s32 index=0;

	if(ms_buflen(proto)>0){
		ms_strcats(tbuf, plisturl, "%s://", proto);
	}	
	if(ms_buflen(authorization)>0){
		ms_strcats(tbuf, plisturl, "@%s@", authorization);
	}
	if(ms_buflen(hostname)>0){
		ms_strcats(tbuf, plisturl, "%s", hostname);
	}
	if(ms_buflen(path)>0){
		if(port>0){
			ms_strcats(tbuf, plisturl, ":%d", port);
		}
		if(msstr_api_isCasestr(path, "m3u8")){
			ms_strcats(tbuf, plisturl, "%s",path);
			ms_u32 offset_path=ms_buflen(path)-ms_buflen(".m3u8");
			ms_sprintf(&plisturl[offset_path], "_[%03d:%03d].m3u8", 0,(listnum-1));
		}else{
			ms_strcats(tbuf, plisturl, "/%s_[%03d:%03d]", path, 0,(listnum-1));
		}
	}else{
		ms_strcats(tbuf, plisturl, ":[%d:%d]", port,(port+(listnum-1)));
	}
}
/*在字符串info中查找key=val键值对，并将val拷贝到strVal中返回*/
ms_bool msstr_api_findTag(char *strVal, int valLen, const char *strKey, const char *info)
{
	const char *p;
	char tag[128], *q;
    p = info;
	if(ms_null==p ){
		return ms_false;
	}
	if (*p == '?'){
		p++;
	}
	for(;;) {
		q = tag;
		while (*p != '\0' && *p != '=' && *p != '&') {
			if ((q - tag) < sizeof(tag) - 1){
				*q++ = *p;
			}
			p++;
		}
		*q = '\0';
		q = strVal;
		if (*p == '=') {
			p++;
			while (*p != '&' && *p != '\0') {
				if ((q - strVal) < valLen - 1) {
					if (*p == '+'){
						*q++ = ' ';
					}else{
						*q++ = *p;
					}
				}
               	p++;
            }
        }
		*q = '\0';
		if (!strcmp(tag, strKey)){
			return ms_true;
		}
		if (*p != '&'){
			break;
		}
		p++;
	}
	return ms_false;
}

/*将strIn字符串中的substrSrc字符串替换为substrDst字符串，并输出到strOut*/
ms_string msstr_api_replace(ms_cstring strIn, ms_cstring substrSrc, ms_cstring substrDst, ms_string strOut)
{  
 	char *p;
 	char *_out = strOut;
	const char *_str = strIn;
	const char *_src = substrSrc;
	const char *_dst = substrDst;
	int src_len = strlen(_src);
	int dst_len = strlen(_dst);
	int len = 0;
	do{
 		p = strstr(_str, _src);
 		if(p == 0){
			strcpy(_out, _str);
			return strOut;
		}
		len = p - _str;
		memcpy(_out, _str, len);
		memcpy(_out + len, _dst, dst_len);
		_str = p + src_len;
		_out = _out + len + dst_len;
	} while(p);
	return strOut;
}

/*统一转换为大写字母:UppercaseLetters*/
ms_void msstr_api_outULetters(ms_string ms_in instr,ms_string ms_out outstr)
{
	ms_s32 len= strlen(instr);
	ms_s32 index=0;
	for(index=0;index<len;index++){
		if( ('a'-1)<instr[index] && instr[index]<('z'-1) ){
			outstr[index]=instr[index]-32;
		}else{
			outstr[index]=instr[index];
		}
	}
}
/*统一转换为小写字母:LowercaseLetters*/
ms_void msstr_api_outLLetters(ms_string ms_in instr,ms_string ms_out outstr)
{
	ms_s32 len= strlen(instr);
	ms_s32 index=0;
	for(index=0;index<len;index++){
		if( ('A'-1)<instr[index] && instr[index]<('Z'-1) ){
			outstr[index]=instr[index]+32;
		}else{
			outstr[index]=instr[index];
		}
	}
}
/*获取URL中不包含参数的path*/
ms_void msstr_api_getUrlRealPath(ms_string path,ms_string realPath)
{
	ms_string str_array_item1[256];
	ms_byte pathTmp[1024];
	ms_strcpy(pathTmp, path)
	ms_u08 num=msstr_api_split(pathTmp, "?", str_array_item1);
	if(num>1){//存在参数
		ms_strcpy(realPath, str_array_item1[0]);
	}else{
		ms_strcpy(realPath, pathTmp);
	}
}
ms_void msstr_api_setString(ms_string    buf,const char *format,...)
{
	va_list arg;
	va_start(arg,format);
	ms_byte setstr[512]={0};
	/*获取参数时，一定要小心。否则会导致段错误*/
	vsnprintf(setstr,ms_bufsize(setstr), format,arg);
	if(ms_false==msstr_api_isCasestr(buf, setstr)){
		ms_s08 tbuf[512]={0};
		ms_strcats(tbuf,buf, "#%s", setstr);
	}
	va_end(arg);
}

#undef MSSTRING_C

